/**
 * create by zhangpu date:2015年3月12日
 */
package com.acooly.module.openapi.client.provider.wft.marshall;

import com.acooly.core.utils.Reflections;
import com.acooly.core.utils.Strings;
import com.acooly.module.openapi.client.api.exception.ApiClientException;
import com.acooly.module.openapi.client.api.marshal.ApiUnmarshal;
import com.acooly.module.openapi.client.api.message.MessageFactory;
import com.acooly.module.openapi.client.provider.wft.domain.WftResponse;
import com.acooly.module.openapi.client.provider.wft.enums.WftServiceEnum;
import com.acooly.module.openapi.client.provider.wft.support.WftAlias;
import com.acooly.module.openapi.client.provider.wft.utils.XmlUtils;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;

/**
 * @author zhangpu
 */
@Service
@Slf4j
public class WftResponseUnmarshall extends WftMarshallSupport
        implements ApiUnmarshal<WftResponse, String> {

    private static final Logger logger = LoggerFactory.getLogger(WftResponseUnmarshall.class);

    @Resource(name = "wftMessageFactory")
    private MessageFactory messageFactory;

    @SuppressWarnings("unchecked")
    @Override
    public WftResponse unmarshal(String message, String serviceName) {
        try {
            logger.info("响应报文:{}", message);
            // 验签
            Map<String, String> responseMap = XmlUtils.toMap(message.getBytes(), "utf-8");
            String status = responseMap.get("status");
            if (Strings.equals(status, "0")) {
                String partnerId = responseMap.get("mch_id");
                SortedMap<String,String> sort=new TreeMap<String,String>(responseMap);
                verifySign(sort, partnerId);
            } else {
                log.info("响应状态status={}通讯失败", status);
                throw new ApiClientException(responseMap.get("message"));
            }
            return doUnmarshall(responseMap, serviceName);
        } catch (Exception e) {
            throw new ApiClientException("解析响应报文错误:" + e.getMessage());
        }
    }

    protected WftResponse doUnmarshall(Map<String, String> message, String serviceName) {
        WftResponse response =
                (WftResponse) messageFactory.getResponse(WftServiceEnum.find(serviceName).getKey());
        Set<Field> fields = Reflections.getFields(response.getClass());
        String key = null;
        for (Field field : fields) {
            WftAlias wftAlias = field.getAnnotation(WftAlias.class);
            if (wftAlias != null && Strings.isNotBlank(wftAlias.value())) {
                key = wftAlias.value();
            } else {
                key = field.getName();
            }
            Reflections.invokeSetter(response, field.getName(), message.get(key));
        }
        return response;
    }

    public void verifySign(SortedMap<String, String> params, String partnerId) {
        try {
            String signature = params.get("sign");
            doVerifySign(params, signature, partnerId);
            log.info("验签成功");
        } catch (Exception e) {
            log.info("验签失败，响应报文：{}", params);
            throw new ApiClientException("响应报文验签失败");
        }
    }

    public void setMessageFactory(MessageFactory messageFactory) {
        this.messageFactory = messageFactory;
    }
}
